#include "Stack.h"
using namespace CSCI123;

Stack::Stack() : top(NULL) {
	/* empty */
}

/* copy constructor
 * invoked whenever a copy of an object is needed
 * such as in passing an object by value to a function
 * returning an object by value from a function or initializing an object with a 
 * copy of another object of the same class
 */
Stack::Stack(const Stack& aStack) {
	if (aStack.top == NULL) {
		top = NULL;  // original list is empty
	} else {  
		// copy first node
		top = new Frame;
		top->data = aStack.top->data;
		// copy rest of list
		FramePtr newPtr = top;    // new list pointer
		FramePtr origPtr = aStack.top->next;

		for(;origPtr != NULL;origPtr = origPtr->next){  
			newPtr->next = new Frame;
			newPtr = newPtr->next;
			newPtr->data = origPtr->data;
		}
		newPtr->next = NULL;
	}
}

Stack::~Stack() {
	while(!isEmpty()) {
		pop();
	}
	top = NULL;
}

string Stack::pop() {
	string data = "";
	if(!isEmpty()) {
		FramePtr frame = top;
		data = frame->data;	// get the top string
		top = frame->next;
		delete frame;
	}
	return data;
}

void Stack::push(const string& aString) {
	FramePtr frame = new Frame;
	frame->data = aString;
	if(!isEmpty())
		frame->next = top;
	else
		frame->next = NULL;
	top = frame;
}

bool Stack::isEmpty() const {
	return top == NULL;
}

void Stack::getTop(string& aTopData) const {
	if(!isEmpty()) {
		aTopData = top->data;
	}
}

ostream& CSCI123::operator <<(ostream& out, const Stack& aStack) {	
	if(aStack.top == NULL)
		out << "Empty Stack!";
	for(FramePtr cur = aStack.top; cur != NULL; cur = cur->next) {
		if(cur == aStack.top)
			out << "top->";
		out << "\t" << cur->data << endl;
	}
	return out;
}
